package com.ruoyi.ldzlsb.util;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.ldzlsb.domain.SbInspectionCycleConfig;
import com.ruoyi.ldzlsb.domain.SbInspectionPlan;

/**
 * 巡检日期计算工具类
 * 
 * @author ruoyi
 */
public class InspectionDateCalculator {
    
    private static final Logger logger = LoggerFactory.getLogger(InspectionDateCalculator.class);
    
    /**
     * 计算巡检日期列表
     * 
     * @param plan 巡检计划
     * @param cycleConfig 周期配置
     * @return 巡检日期列表
     */
    public static List<Date> calculateInspectionDates(SbInspectionPlan plan, SbInspectionCycleConfig cycleConfig) {
        List<Date> inspectionDates = new ArrayList<>();
        
        // 检查计划起止日期是否有效
        if (plan.getStartDate() == null || plan.getEndDate() == null) {
            logger.error("计划起止日期无效，planId={}", plan.getPlanId());
            return inspectionDates;
        }
        
        // 检查周期类型
        String cycleType = cycleConfig.getCycleType();
        if (StringUtils.isEmpty(cycleType)) {
            logger.error("周期类型为空，planId={}", plan.getPlanId());
            return inspectionDates;
        }
        
        try {
            switch (cycleType) {
                case "1": // 每天
                    inspectionDates = calculateDailyDates(plan.getStartDate(), plan.getEndDate(), cycleConfig.getCycleValue());
                    break;
                case "2": // 每周
                    inspectionDates = calculateWeeklyDates(plan.getStartDate(), plan.getEndDate(), cycleConfig.getCycleValue(), cycleConfig.getConfigData());
                    break;
                case "3": // 每月
                    inspectionDates = calculateMonthlyDates(plan.getStartDate(), plan.getEndDate(), cycleConfig.getCycleValue(), cycleConfig.getConfigData());
                    break;
                case "4": // 每季度
                    inspectionDates = calculateQuarterlyDates(plan.getStartDate(), plan.getEndDate(), cycleConfig.getCycleValue(), cycleConfig.getConfigData());
                    break;
                case "5": // 每年
                    inspectionDates = calculateYearlyDates(plan.getStartDate(), plan.getEndDate(), cycleConfig.getCycleValue(), cycleConfig.getConfigData());
                    break;
                case "6": // 自定义
                    inspectionDates = calculateCustomDates(plan.getStartDate(), plan.getEndDate(), cycleConfig.getConfigData());
                    break;
                default:
                    logger.error("不支持的周期类型: {}, planId={}", cycleType, plan.getPlanId());
            }
        } catch (Exception e) {
            logger.error("计算巡检日期异常: planId={}, cycleType={}", plan.getPlanId(), cycleType, e);
        }
        
        return inspectionDates;
    }
    
    /**
     * 计算每天的巡检日期
     */
    private static List<Date> calculateDailyDates(Date startDate, Date endDate, Integer interval) {
        List<Date> dates = new ArrayList<>();
        
        // 默认每天
        if (interval == null || interval < 1) {
            interval = 1;
        }
        
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(startDate);
        
        // 清除时分秒
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        
        while (!calendar.getTime().after(endDate)) {
            dates.add(calendar.getTime());
            // 增加指定天数
            calendar.add(Calendar.DATE, interval);
        }
        
        return dates;
    }
    
    /**
     * 计算每周的巡检日期
     */
    private static List<Date> calculateWeeklyDates(Date startDate, Date endDate, Integer interval, String configData) {
        List<Date> dates = new ArrayList<>();
        
        // 默认每周
        if (interval == null || interval < 1) {
            interval = 1;
        }
        
        // 解析配置数据，获取周几 (1-7 表示周一到周日)
        List<Integer> weekdays = parseWeekdays(configData);
        if (weekdays.isEmpty()) {
            // 默认周一
            weekdays.add(Calendar.MONDAY);
        }
        
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(startDate);
        
        // 清除时分秒
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        
        while (!calendar.getTime().after(endDate)) {
            int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
            // Calendar中周日是1，周一是2...周六是7
            // 转换为我们的1-7（周一到周日）
            int adjustedDayOfWeek = (dayOfWeek == Calendar.SUNDAY) ? 7 : dayOfWeek - 1;
            
            if (weekdays.contains(adjustedDayOfWeek)) {
                dates.add(calendar.getTime());
            }
            
            // 每天递增
            calendar.add(Calendar.DATE, 1);
            
            // 如果是周日且间隔大于1，则跳到下一个间隔的周一
            if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY && interval > 1) {
                calendar.add(Calendar.DATE, (interval - 1) * 7);
            }
        }
        
        return dates;
    }
    
    /**
     * 计算每月的巡检日期
     */
    private static List<Date> calculateMonthlyDates(Date startDate, Date endDate, Integer interval, String configData) {
        List<Date> dates = new ArrayList<>();
        
        // 默认每月
        if (interval == null || interval < 1) {
            interval = 1;
        }
        
        // 解析配置数据，获取日期列表 (1-31)
        List<Integer> monthDays = parseMonthDays(configData);
        if (monthDays.isEmpty()) {
            // 默认每月1号
            monthDays.add(1);
        }
        
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(startDate);
        
        // 清除时分秒
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        
        // 设置为当月第一天
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        
        while (!calendar.getTime().after(endDate)) {
            int maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
            
            for (Integer day : monthDays) {
                if (day <= maxDay) {
                    calendar.set(Calendar.DAY_OF_MONTH, day);
                    Date inspectionDate = calendar.getTime();
                    if (!inspectionDate.before(startDate) && !inspectionDate.after(endDate)) {
                        dates.add(inspectionDate);
                    }
                }
            }
            
            // 增加月份
            calendar.add(Calendar.MONTH, interval);
        }
        
        return dates;
    }
    
    /**
     * 计算每季度的巡检日期
     */
    private static List<Date> calculateQuarterlyDates(Date startDate, Date endDate, Integer interval, String configData) {
        List<Date> dates = new ArrayList<>();
        
        // 默认每季度
        if (interval == null || interval < 1) {
            interval = 1;
        }
        
        // 解析配置数据
        JSONObject config = parseConfigData(configData);
        
        // 默认每季度第一个月的1号
        List<Integer> months = new ArrayList<>();
        List<Integer> days = new ArrayList<>();
        
        if (config != null) {
            JSONArray monthsArray = config.getJSONArray("months");
            if (monthsArray != null && !monthsArray.isEmpty()) {
                for (int i = 0; i < monthsArray.size(); i++) {
                    months.add(monthsArray.getIntValue(i));
                }
            }
            
            JSONArray daysArray = config.getJSONArray("days");
            if (daysArray != null && !daysArray.isEmpty()) {
                for (int i = 0; i < daysArray.size(); i++) {
                    days.add(daysArray.getIntValue(i));
                }
            }
        }
        
        // 如果没有配置，使用默认值
        if (months.isEmpty()) {
            // 每季度第一个月 (1, 4, 7, 10)
            months.add(0); // 相对于季度开始的月份，0表示第一个月
        }
        
        if (days.isEmpty()) {
            // 默认每月1号
            days.add(1);
        }
        
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(startDate);
        
        // 清除时分秒
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        
        // 计算当前季度
        int currentQuarter = (calendar.get(Calendar.MONTH) / 3) + 1;
        
        // 设置为当前季度的第一天
        calendar.set(Calendar.MONTH, (currentQuarter - 1) * 3);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        
        while (!calendar.getTime().after(endDate)) {
            int quarterStartMonth = calendar.get(Calendar.MONTH);
            
            for (Integer monthOffset : months) {
                // 设置为季度内的月份
                calendar.set(Calendar.MONTH, quarterStartMonth + monthOffset);
                
                int maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
                
                for (Integer day : days) {
                    if (day <= maxDay) {
                        calendar.set(Calendar.DAY_OF_MONTH, day);
                        Date inspectionDate = calendar.getTime();
                        if (!inspectionDate.before(startDate) && !inspectionDate.after(endDate)) {
                            dates.add(inspectionDate);
                        }
                    }
                }
            }
            
            // 增加季度
            calendar.set(Calendar.MONTH, quarterStartMonth);
            calendar.add(Calendar.MONTH, 3 * interval);
        }
        
        return dates;
    }
    
    /**
     * 计算每年的巡检日期
     */
    private static List<Date> calculateYearlyDates(Date startDate, Date endDate, Integer interval, String configData) {
        List<Date> dates = new ArrayList<>();
        
        // 默认每年
        if (interval == null || interval < 1) {
            interval = 1;
        }
        
        // 解析配置数据
        JSONObject config = parseConfigData(configData);
        
        // 默认每年1月1号
        List<Integer> months = new ArrayList<>();
        List<Integer> days = new ArrayList<>();
        
        if (config != null) {
            JSONArray monthsArray = config.getJSONArray("months");
            if (monthsArray != null && !monthsArray.isEmpty()) {
                for (int i = 0; i < monthsArray.size(); i++) {
                    months.add(monthsArray.getIntValue(i));
                }
            }
            
            JSONArray daysArray = config.getJSONArray("days");
            if (daysArray != null && !daysArray.isEmpty()) {
                for (int i = 0; i < daysArray.size(); i++) {
                    days.add(daysArray.getIntValue(i));
                }
            }
        }
        
        // 如果没有配置，使用默认值
        if (months.isEmpty()) {
            // 默认1月
            months.add(Calendar.JANUARY);
        }
        
        if (days.isEmpty()) {
            // 默认1号
            days.add(1);
        }
        
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(startDate);
        
        // 清除时分秒
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        
        int startYear = calendar.get(Calendar.YEAR);
        
        calendar.setTime(endDate);
        int endYear = calendar.get(Calendar.YEAR);
        
        for (int year = startYear; year <= endYear; year += interval) {
            calendar.set(Calendar.YEAR, year);
            
            for (Integer month : months) {
                calendar.set(Calendar.MONTH, month);
                int maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
                
                for (Integer day : days) {
                    if (day <= maxDay) {
                        calendar.set(Calendar.DAY_OF_MONTH, day);
                        Date inspectionDate = calendar.getTime();
                        if (!inspectionDate.before(startDate) && !inspectionDate.after(endDate)) {
                            dates.add(inspectionDate);
                        }
                    }
                }
            }
        }
        
        return dates;
    }
    
    /**
     * 计算自定义的巡检日期
     */
    private static List<Date> calculateCustomDates(Date startDate, Date endDate, String configData) {
        List<Date> dates = new ArrayList<>();
        
        if (StringUtils.isEmpty(configData)) {
            logger.error("自定义巡检日期的配置数据为空");
            return dates;
        }
        
        try {
            JSONArray datesArray = JSON.parseArray(configData);
            if (datesArray != null && !datesArray.isEmpty()) {
                for (int i = 0; i < datesArray.size(); i++) {
                    try {
                        String dateStr = datesArray.getString(i);
                        Date inspectionDate = DateUtils.parseDate(dateStr);
                        
                        // 仅添加在起止日期范围内的日期
                        if (!inspectionDate.before(startDate) && !inspectionDate.after(endDate)) {
                            dates.add(inspectionDate);
                        }
                    } catch (Exception e) {
                        logger.error("解析自定义日期失败: {}", datesArray.getString(i), e);
                    }
                }
            }
        } catch (Exception e) {
            logger.error("解析自定义巡检日期配置失败: {}", configData, e);
        }
        
        return dates;
    }
    
    /**
     * 解析周几配置 (1-7 表示周一到周日)
     */
    private static List<Integer> parseWeekdays(String configData) {
        List<Integer> weekdays = new ArrayList<>();
        
        if (StringUtils.isEmpty(configData)) {
            return weekdays;
        }
        
        try {
            JSONObject config = JSON.parseObject(configData);
            JSONArray weekdaysArray = config.getJSONArray("weekdays");
            
            if (weekdaysArray != null && !weekdaysArray.isEmpty()) {
                for (int i = 0; i < weekdaysArray.size(); i++) {
                    int weekday = weekdaysArray.getIntValue(i);
                    if (weekday >= 1 && weekday <= 7) {
                        weekdays.add(weekday);
                    }
                }
            }
        } catch (Exception e) {
            logger.error("解析周几配置失败: {}", configData, e);
        }
        
        return weekdays;
    }
    
    /**
     * 解析月份天数配置 (1-31)
     */
    private static List<Integer> parseMonthDays(String configData) {
        List<Integer> days = new ArrayList<>();
        
        if (StringUtils.isEmpty(configData)) {
            return days;
        }
        
        try {
            JSONObject config = JSON.parseObject(configData);
            JSONArray daysArray = config.getJSONArray("days");
            
            if (daysArray != null && !daysArray.isEmpty()) {
                for (int i = 0; i < daysArray.size(); i++) {
                    int day = daysArray.getIntValue(i);
                    if (day >= 1 && day <= 31) {
                        days.add(day);
                    }
                }
            }
        } catch (Exception e) {
            logger.error("解析月份天数配置失败: {}", configData, e);
        }
        
        return days;
    }
    
    /**
     * 解析配置数据为JSON对象
     */
    private static JSONObject parseConfigData(String configData) {
        if (StringUtils.isEmpty(configData)) {
            return null;
        }
        
        try {
            return JSON.parseObject(configData);
        } catch (Exception e) {
            logger.error("解析配置数据失败: {}", configData, e);
            return null;
        }
    }
} 